package com.xinz.server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.dom4j.Element;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpRequestEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xinz.Constants;
import com.xinz.action.PlayerAction;
import com.xinz.config.ConfigHelper;
import com.xinz.config.GlobalConfig;
import com.xinz.config.MapperManager;
import com.xinz.dao.DBManager;
import com.xinz.protocal.Session;
import com.xinz.protocal.config.DefaultConfigFactory;

public class SpotServer {

	public static int serverId;
	
	private static final Logger log = LoggerFactory.getLogger(SpotServer.class);
	
	public static void main(String[] args) {
		
		if(args.length < 1) {
			log.error("please set server id");
			System.exit(0);
		}
		
		try {
			serverId = Integer.parseInt(args[0]);
			Constants.SERVER_ID = serverId;
			log.info("appserver {}", serverId);
			
			long startTime = System.currentTimeMillis();
			
			// 配置文件初始化
			log.info("init config.xml");
			GlobalConfig.init(Constants.CONFIG_FILE);
			
			// 初始化DB
			log.info("init mongo");
			DBManager.initMongo();
			
			// 资源信息初始化
			log.info("init config");
			MapperManager.init();
			ConfigHelper.init();
			
			log.info("start server");
			
			Element serverElement = GlobalConfig.getServer(serverId);
			String host = serverElement.attributeValue("host");
			int port = Integer.parseInt(serverElement.attributeValue("port"));
			SpotNettyServer server = SpotNettyServer.createSocketServer(host, port, new DefaultConfigFactory());
			server.addSessionListener(new SessionListener() {

				@Override
				public void onSessionCreate(Session session) {
					session.registerAll(new PlayerAction());
				}

				@Override
				public void onSessionClose(Session session) {
					
				}
				
			});
			server.run();
			
			long endTime = System.currentTimeMillis();
			log.info("start server use time:" + (endTime - startTime));
		}
		catch(Throwable e) {
			e.printStackTrace();
			log.error("start server error", e);
			System.exit(0);
		}
	}
	
	private static class HttpServerPipeFactory implements ChannelPipelineFactory {
		
		private SimpleChannelUpstreamHandler handler = null;
		
		public HttpServerPipeFactory(SimpleChannelUpstreamHandler handler) {
			this.handler = handler;
		}

		@Override
		public ChannelPipeline getPipeline() throws Exception {
			// Create a default pipeline implementation
			ChannelPipeline pipeline = Channels.pipeline();
			pipeline.addLast("decoder", new HttpRequestDecoder());
			pipeline.addLast("encoder", new HttpRequestEncoder());
			// pipeline.addLast("pipelineExecutor", new ExecutionHandler(new
			// OrderedMemoryAwareThreadPoolExecutor(1000, 0, 0)));
			// http处理handler
			pipeline.addLast("handler", handler);
			return null;
		}
	}
	
	/**
	 * 启动管理接口
	 */
	public static void startAdminServer() {
		ServerBootstrap bootStrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
		bootStrap.setPipelineFactory(new HttpServerPipeFactory(new SpotAdminServerHandler()));
		
		Element serverElement = GlobalConfig.getServer(serverId);
		String host = serverElement.attributeValue("host");
		int port = Integer.parseInt(serverElement.attributeValue("admin_port"));
		
		bootStrap.bind(new InetSocketAddress(host, port));
		
		log.info("start admin server host:" + host + ",port:" + port);
	}
}
